package com.mettle.loyaltycard.model;

import java.util.Date;

import junit.framework.Assert;

import org.junit.Test;

public class LoyaltyCardTest {

	@Test
	public void testUpdateCustomerForBlankFields() {
		LoyaltyCard lc = new LoyaltyCard(1);
		Customer sampleCustomer = CustomerTest.sampleCustomer;
		lc.setCustomer(sampleCustomer);
		lc.updateCustomer("", "");
		Assert.assertEquals(sampleCustomer.getName(), lc.getCustomer().getName());
		Assert.assertEquals(sampleCustomer.getEmail(), lc.getCustomer().getEmail());
		lc.updateCustomer(null, null);
		Assert.assertEquals(sampleCustomer.getName(), lc.getCustomer().getName());
		Assert.assertEquals(sampleCustomer.getEmail(), lc.getCustomer().getEmail());

	}

	@Test
	public void testUpdateCustomerForNonBlankFields() {
		LoyaltyCard lc = new LoyaltyCard(1);
		Customer sampleCustomer = CustomerTest.sampleCustomer;
		lc.setCustomer(sampleCustomer);
		Assert.assertEquals(lc, sampleCustomer.getLoyaltyCard());
		lc.updateCustomer("updated", "updated");
		Assert.assertEquals("updated", lc.getCustomer().getName());
		Assert.assertEquals("updated", lc.getCustomer().getEmail());

	}

	@Test
	public void testGetPointsForNormalUser() {
		LoyaltyCard lc = new LoyaltyCard(1);
		for (Double amount = 1.0; amount <26000; amount++) {
			testForAmount(lc, amount, 1, 100);
		}
	}
	
	@Test
	public void testGetPointsForSilverUser() {
		LoyaltyCard lc = new LoyaltyCard(1);
		lc.setMembershipType(MembershipType.SILVER);
		for (Double amount = 1.0; amount <26000; amount++) {
			testForAmount(lc, amount, 2, 100);
		}
	}
	
	@Test
	public void testAddTransactionForNormalMembership() {
		LoyaltyCard lc = new LoyaltyCard(0);
		Date transactionDate = new Date();
		lc.addTransaction(550.0, transactionDate, 1L);
		Assert.assertEquals(550.0, lc.getTotalAmount());
		Assert.assertEquals(MembershipType.NORMAL, lc.getMembershipType());
		Assert.assertEquals(Integer.valueOf(105), lc.getLoyaltyPoints());
		Assert.assertEquals(1, lc.getTransactions().size());
		Transaction transaction = lc.getTransactions().get(0);
		Assert.assertEquals(Long.valueOf(1L), transaction.getTransactionId());
		Assert.assertEquals(Double.valueOf(550.0), transaction.getPurchaseAmount());
		Assert.assertEquals(Integer.valueOf(5), transaction.getPointsEarned());
		Assert.assertEquals(transactionDate, transaction.getPurchaseDate());
		lc.addTransaction(25000.0, transactionDate, 2L);
		Assert.assertEquals(25550.0, lc.getTotalAmount());
		Assert.assertEquals(MembershipType.SILVER, lc.getMembershipType());
		Assert.assertEquals(Integer.valueOf(355), lc.getLoyaltyPoints());
		Assert.assertEquals(2, lc.getTransactions().size());
	}
	
	@Test
	public void testAddTransactionForGoldMembership() {
		LoyaltyCard lc = new LoyaltyCard(0);
		lc.setMembershipType(MembershipType.GOLD);
		lc.addTransaction(550.0, new Date(), 1L);
		Assert.assertEquals(550.0, lc.getTotalAmount());
		Assert.assertEquals(MembershipType.GOLD, lc.getMembershipType());
		Assert.assertEquals(Integer.valueOf(125), lc.getLoyaltyPoints());
		Assert.assertEquals(1, lc.getTransactions().size());
		lc.addTransaction(25000.0, new Date(), 2L);
		Assert.assertEquals(25550.0, lc.getTotalAmount());
		Assert.assertEquals(MembershipType.GOLD, lc.getMembershipType());
		Assert.assertEquals(Integer.valueOf(1375), lc.getLoyaltyPoints());
		Assert.assertEquals(2, lc.getTransactions().size());
	}
	
	@Test
	public void testGetPointsForGoldUser() {
		LoyaltyCard lc = new LoyaltyCard(1);
		lc.setMembershipType(MembershipType.GOLD);
		for (Double amount = 1.0; amount <26000; amount++) {
			testForAmount(lc, amount, 25, 500);
		}
	}

	protected void testForAmount(LoyaltyCard lc, Double amount, Integer multiplier, Integer step) {
		Integer points =lc.getPointsForTransaction(amount);
		Integer expected = Integer.valueOf((multiplier * (int)(amount/step)));
		Assert.assertEquals("Amount: " + amount, expected, points);
	}
}
